package com.itaming.lycheeframework.support.utils;

import lombok.experimental.UtilityClass;

import java.util.function.Function;

/**
 * Number工具类
 *
 * @author A.Ming
 */
@UtilityClass
public class NumberUtil {

    /**
     * 转为为{@link Byte}
     *
     * @param obj 待转换对象
     * @return Byte
     */
    public static Byte toByte(Object obj) {
        return toByte(obj, null);
    }

    /**
     * 转为为{@link Byte}
     *
     * @param obj          待转换对象
     * @param defaultValue 默认值
     * @return Byte
     */
    public static Byte toByte(Object obj, Byte defaultValue) {
        return obj instanceof Byte ? (Byte) obj : parse(obj, defaultValue, Number::byteValue, Byte::valueOf);
    }

    /**
     * 转为{@link Short}
     *
     * @param obj 待转换对象
     * @return Short
     */
    public static Short toShort(Object obj) {
        return toShort(obj, null);
    }

    /**
     * 转为{@link Short}
     *
     * @param obj          待转换对象
     * @param defaultValue 默认值
     * @return Short
     */
    public static Short toShort(Object obj, Short defaultValue) {
        return obj instanceof Short ? (Short) obj : parse(obj, defaultValue, Number::shortValue, Short::valueOf);
    }

    /**
     * 转为{@link Integer}
     *
     * @param obj 待转换对象
     * @return Integer
     */
    public static Integer toInteger(Object obj) {
        return toInteger(obj, null);
    }

    /**
     * 转为{@link Integer}
     *
     * @param obj          待转换对象
     * @param defaultValue 默认值
     * @return Integer
     */
    public static Integer toInteger(Object obj, Integer defaultValue) {
        return obj instanceof Integer ? (Integer) obj : parse(obj, defaultValue, Number::intValue, Integer::valueOf);
    }

    /**
     * 转为{@link Long}
     *
     * @param obj 待转换对象
     * @return Integer
     */
    public static Long toLong(Object obj) {
        return toLong(obj, null);
    }

    /**
     * 转为{@link Long}
     *
     * @param obj          待转换对象
     * @param defaultValue 默认值
     * @return Long
     */
    public static Long toLong(Object obj, Long defaultValue) {
        return obj instanceof Long ? (Long) obj : parse(obj, defaultValue, Number::longValue, Long::valueOf);
    }

    /**
     * 转为{@link Float}
     *
     * @param obj 待转换字符串
     * @return Float
     */
    public static Float toFloat(Object obj) {
        return toFloat(obj, null);
    }

    /**
     * 转为{@link Float}
     *
     * @param obj          待转换对象
     * @param defaultValue 默认值
     * @return Float
     */
    public static Float toFloat(Object obj, Float defaultValue) {
        return obj instanceof Float ? (Float) obj : parse(obj, defaultValue, Number::floatValue, Float::valueOf);
    }

    /**
     * 转为{@link Double}
     *
     * @param obj 待转换对象
     * @return Double
     */
    public static Double toDouble(Object obj) {
        return toDouble(obj, null);
    }

    /**
     * 转为{@link Double}
     *
     * @param obj          待转换对象
     * @param defaultValue 默认值
     * @return Double
     */
    public static Double toDouble(Object obj, Double defaultValue) {
        return obj instanceof Double ? (Double) obj : parse(obj, defaultValue, Number::doubleValue, Double::valueOf);
    }

    /**
     * 解析
     *
     * @param obj            待转换对象
     * @param defaultValue   默认值
     * @param numberFunction 数字类型转换函数
     * @param commonFunction 通用转换函数
     * @return T
     */
    private static <T> T parse(Object obj, T defaultValue, Function<Number, T> numberFunction, Function<String, T> commonFunction) {
        // null
        if (obj == null) {
            return defaultValue;
        }

        // String, StringBuilder, StringBuffer等
        if (obj instanceof CharSequence && StringUtil.isBlank((CharSequence) obj)) {
            return defaultValue;
        }

        // 数字
        if (obj instanceof Number) {
            return numberFunction.apply((Number) obj);
        }

        // 其他
        try {
            return commonFunction.apply(obj.toString());
        } catch (Exception e) {
            return defaultValue;
        }
    }

}
